/*
 * Copyright (C) 2018 Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
 * Author: Ortega Froysa, Nicolás <nortega@themusicinnoise.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "AssetManager.hpp"

#include "System.hpp"

#include <vector>
#include <stdio.h>

//#define TINYOBJLOADER_IMPLEMENTATION
//#include <tiny_obj_loader.h>
#include <glm/glm.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>

void AssetManager::loadModel(const std::string &path,
		const std::string &name)
{
	Assimp::Importer importer;
	const aiScene *scene = importer.ReadFile(path,
			aiProcess_Triangulate);
	if(not scene)
	{
		System::logger->writeError(importer.GetErrorString());
		return;
	}
	const aiMesh *mesh = scene->mMeshes[0];

	std::vector<struct Vertex> vertices;
	std::vector<unsigned int> indices;

	vertices.reserve(mesh->mNumVertices);
	for(unsigned int i = 0; i < mesh->mNumVertices; ++i)
	{
		aiVector3D pos = mesh->mVertices[i];
		aiVector3D norm = mesh->mNormals[i];

		vertices.push_back({
				glm::vec3(pos.x, pos.y, pos.z),
				glm::vec3(norm.x, norm.y, norm.z)});
	}

	indices.reserve(3 * mesh->mNumFaces);
	for(unsigned int i = 0; i < mesh->mNumFaces; ++i)
	{
		for(unsigned int j = 0; j < 3; ++j)
			indices.push_back(mesh->mFaces[i].mIndices[j]);
	}

	models.insert({ name,
			std::make_shared<Model>(
					vertices, indices)});
}

std::shared_ptr<Model> AssetManager::getModel(
		const std::string &name)
{
	return models.at(name);
}

void AssetManager::unloadModel(const std::string &name) {
	models.erase(name);
}
